package io;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import javax.imageio.ImageIO;
import view.Designer;
public class cssParser {
	
	private static cssParser instance;//instance of this parser
	private BufferedWriter bwCSS;//Buffer to store data before being written to file
	private BufferedWriter bwHTML;
	private StringBuffer sbCSS;
	private StringBuffer sbHTML;
	private BufferedImage watermark;
		private final static int offsetX = 100;//offset the image on the HTML in pixels
	private final static int offsetY = 100;//offset the image on the HTML in pixels
	
	/**
	 * Constructor - private
	 * 
	 * Initialise the string buffers
	 */
	private cssParser(){
		sbCSS = new StringBuffer();
		sbHTML = new StringBuffer();
	}
	/**
	 * Returns a singleton instance of the cssParser
	 * 
	 * @return instance of static cssParser
	 */
	public static cssParser getInstance(){
		if(instance == null){
			instance = new cssParser();
		}
		return instance;
	}
	/**
	 * Creates two files, a CSS and HTML file. Each line is written individually,
	 * each time a DIV id is created, the relevant HTML code is also placed in it's
	 * Separate stringBuffer. This allows for uniform and coherent code in both files.
	 * 
	 * @param prescription - The prescription model object which needs to be exported
	 * @param cssFilename - The filename for the CSS file, needed for the HTML file to link to it
	 */
	private void createCSS(model.Prescription prescription, String cssFilename){ 
		sbCSS.delete(0, sbCSS.length());//Clear arrays and buffers
		sbHTML.delete(0, sbHTML.length());//Clear arrays and buffers
		
		sbHTML.append("<link rel=\"stylesheet\" href=\"" + cssFilename + "\" type=\"text/css\" media=\"screen\" />\n\n"); //Header of HTML file
		//Start CSS File First
		//Header of CSS file
		sbCSS.append("/*\n");
		sbCSS.append("   Serial Number: " + prescription.getSerialNo() + "\n");
		sbCSS.append("   CSS Format Prescription \n");
		sbCSS.append("   Created by Group 4 Designers \n");
		sbCSS.append("*/\n\n");
		//Create DIV element for outer Prescription
		sbCSS.append("/* Element for qhole prescription */\n");
		sbCSS.append("#prescription {\n");
		sbHTML.append("<div id=\"prescription\">\n");
		sbHTML.append("</div>\n");
		sbHTML.append("<div id=\"watermark\"><img src=\"watermark.png\" id=\"stretch\" alt=\"\" /></div>\n\n");
				sbCSS.append("\tposition: absolute;\n");
		sbCSS.append("\tz-index: 0;\n");
		sbCSS.append("\tborder-style: solid;\n");
		sbCSS.append("\tborder-width: 1px;\n");
		sbCSS.append("\tborder-color: #000000;\n");
		sbCSS.append("\tbackground: " + convertToHex(prescription.getBGColour()) + ";\n");
		sbCSS.append("\twidth: " + prescription.getWidth() + "px;\n");
		sbCSS.append("\theight: " + prescription.getHeight() + "px;\n");
		sbCSS.append("\tleft: " + offsetX + ";\n");
		sbCSS.append("\ttop: " + offsetY + ";\n");
		sbCSS.append("}\n\n");
		sbCSS.append("#watermark {\n");
		sbCSS.append("\tz-index: 999;\n");
		sbCSS.append("\twidth: " + prescription.getWidth() +"px;\n");
		sbCSS.append("\theight: " + prescription.getHeight() +"px;\n");
		sbCSS.append("\tposition: absolute;\n");
		sbCSS.append("\tleft: " + offsetX + ";\n");
		sbCSS.append("\ttop: " + offsetY + ";\n");
		sbCSS.append("}\n\n");
		sbCSS.append("#stretch {\n");
		sbCSS.append("\twidth: 100%;\n");
		sbCSS.append("\theight: 100%;\n");
		sbCSS.append("}\n\n");
		int i = 1;
		
		for(model.PrescriptionObject obj : prescription.objects()){//For each of the objects in the prescription create CSS and HTML code
			String id = "Box" + Integer.toString(i);	//Create the ID for the box
			sbHTML.append("<div id=\"" + id + "\">");//Create the HTML code. DIV element with correct ID defined above
			sbHTML.append(obj.getName());
			sbHTML.append("</div>\n");
			sbCSS.append("#" + id + "{\n");	//Create the CSS data
			sbCSS.append("\tposition: absolute;\n");//Positioning will be absolute
			sbCSS.append("\tz-index: " + i + ";\n");//Set the z-index to display the items correctly in browser
			sbCSS.append("\tleft: " + (offsetX + obj.getX()) + ";\n");//Define the location and dimensions of box. In pixels
			sbCSS.append("\ttop: " + (offsetY + obj.getY()) + ";\n");
			sbCSS.append("\twidth: " + obj.getWidth() + ";\n");
			sbCSS.append("\theight: " + obj.getHeight() + ";\n");
			
			
			if(obj.getLineWidth() > 0){//If the box has a border, define it
				sbCSS.append("\tborder-style: solid;\n");
				sbCSS.append("\tborder-width: " + obj.getLineWidth() + "px;\n");
				sbCSS.append("\tborer-color: " + convertToHex(obj.getLineColour()) + ";\n");
			}
			if(!obj.isTransparent()){//If the box is transparent, don't define the fill colour
				sbCSS.append("\tbackground: " + convertToHex(obj.getFillColour()) + ";\n");
			}
			
			sbCSS.append("\tcolor: " + convertToHex(obj.getTextColour()) + ";\n");//Define the text colour
			sbCSS.append("}\n\n");//Break line, twice
			i++;
		}
	}
	/**
	 * Writes data to files. Used twice, once for CSS and once for HTML
	 * 
	 * @param sb - String buffer, the data to be written to file
	 * @param bw - Buffered Writer, used to write data to file
	 */
	private void writeToFile(StringBuffer sb, BufferedWriter bw){
		try{//Try to write data to file
			bw.write(sb.toString());
		} catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException e) {
			e.printStackTrace();
		} finally {
			//Close the BufferedWriter
            try {
                if (bw != null) {
                    bw.flush();
                    bw.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
		}

	}
	
	/**
	 * Main method to be called to export the CSS and HTML files
	 * 
	 * @param pres1 The prescription Object used to create the CSS and HTML files
	 * @param filename - The filename of the file to be saved
	 */
	public void export(model.Prescription pres1, String filename){
		String htmlFilename = "";
		String cssFilename = "";
		
		int slash = filename.lastIndexOf("\\");//Define the filenames for exporting
		cssFilename = filename.substring(slash + 1, filename.length());
		int dot = filename.lastIndexOf(".");
		htmlFilename = filename.substring(0, dot) + ".html";
	
		try {	//Try to create the two buffered writers
			bwCSS = new BufferedWriter(new FileWriter(filename));
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			bwHTML = new BufferedWriter(new FileWriter(htmlFilename));
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {//Read file as image
			watermark = ImageIO.read(Designer.class.getResource("/images/watermark.png"));
		} catch (IOException e) {
			e.printStackTrace();
		}		
		String watermark_filename = filename.substring(0, slash) + "/watermark.png";
		try {
			ImageIO.write(watermark, "png", new File(watermark_filename));
		} catch (IOException e) {
			e.printStackTrace();
		}
		createCSS(pres1, cssFilename);//Create the CSS and HTML
		writeToFile(sbCSS, bwCSS);//Write data to corresponding files
		writeToFile(sbHTML, bwHTML);
	}
	/**
	 * Function to convert integer RGB values into hex values that can be used
	 * for web functions, such as CSS or XHTML formatting
	 * 
	 * @param red integer value of RGB
	 * @param green integer value of RGB
	 * @param blue integer value of RGB
	 * @return - String value in the format #000000
	 */
	private String convertToHex(Color colour){
		String redHex = Integer.toHexString(colour.getRed());
		String greenHex = Integer.toHexString(colour.getGreen());
		String blueHex = Integer.toHexString(colour.getBlue());
		/*
		 * The following if statement compensate for the Integer.toHexString method
		 * omitting a trailing zero, leading to a non functioning colour. This will
		 * add a zero if the colour ends in zero.
		 */
		if(redHex.length() < 2){
			redHex += "0";
		}
		if(greenHex.length() < 2){
			greenHex += "0";
		}		
		if(blueHex.length() < 2){
			blueHex += "0";
		}
		return "#" + redHex + greenHex + blueHex;//Return HTML hex colour
	}
}